﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Data;
using System.Text;

namespace DGen
{
    public static partial class DText
    {
        /// <summary>
        /// A variety of static methods to convert objects to text in a readable human fashion without overriding the ToString method.
        /// </summary>
        public static class ObjectToString
        {

            /// <summary>
            /// Dictionary to tab separated text with line breaks.
            /// </summary>
            /// <param name="myDict"></param>
            /// <returns></returns>
            public static string DictionaryToString (Dictionary<string, string> myDict)
            {
                StringBuilder sb = new StringBuilder ();
                int longestKey = 0;
                int longestValue = 0;
                foreach (KeyValuePair<string, string> kvp in myDict)
                {
                    longestKey = Math.Max (kvp.Key.ToString ().Length, longestKey);
                    longestValue = Math.Max (kvp.Value.ToString ().Length, longestValue);
                    
                }
                longestKey++;
                longestValue++;
                
                
                string textFormat = "{0,-" + longestKey.ToString () + "}{1," + longestValue.ToString () + "}\n";
                
                foreach (KeyValuePair<string, string> kvp in myDict)
                {
                    string k = kvp.Key.ToString ();
                    string v = kvp.Value.ToString ();
                    
                    sb.AppendFormat (textFormat, k, v);
                    
                    
                }
                return sb.ToString ();
            }
            /// <summary>
            /// returns a string representation of dictionary sorted by value (ascending).
            /// </summary>
            /// <param name="myDict"></param>
            /// <param name="sortByValue"></param>
            /// <returns></returns>
            public static string DictionaryToString (Dictionary<string, string> myDict, bool sortByValue)
            {
                List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>> (myDict);
                myList.Sort ((firstPair, nextPair) => { return firstPair.Value.CompareTo (nextPair.Value); });
                return DictionaryToString (myDict);
            }


            /// <summary>
            /// returns formatted string output of numeric Dictionary (unsorted)
            /// </summary>
            /// <param name="myDict"></param>
            /// <returns></returns>
            public static string DictionaryToString (Dictionary<int, int> myDict)
            {
                StringBuilder sb = new StringBuilder ();
                int longestKey = 0;
                int longestValue = 0;
                foreach (KeyValuePair<int, int> kvp in myDict)
                {
                    longestKey = Math.Max (kvp.Key.ToString ().Length, longestKey);
                    longestValue = Math.Max (kvp.Value.ToString ().Length, longestValue);

                }
                longestKey++;
                longestValue++;
                
                string textFormat = "{0,-" + longestKey.ToString () + "}{1," + longestValue.ToString () + "}\n";
                
                
                foreach (KeyValuePair<int, int> kvp in myDict)
                {
                    sb.AppendFormat (textFormat, kvp.Key, kvp.Value);
                    
                }
                return sb.ToString ();
            }

            /// <summary>
            /// returns formatted string output of numeric Dictionary (sorted by Value descending)
            /// </summary>
            /// <param name="myDict"></param>
            /// <param name="sortByValue"></param>
            /// <returns></returns>
            public static string DictionaryToString (Dictionary<int, int> myDict, bool sortByValue)
            {
                StringBuilder sb = new StringBuilder ();
                List<KeyValuePair<int, int>> myList = new List<KeyValuePair<int, int>> (myDict);
                myList.Sort ((firstPair, nextPair) => { return 0 - firstPair.Value.CompareTo (nextPair.Value); });
                Dictionary<int, int> newDict = new Dictionary<int, int> ();
                foreach (var b in myList)
                {
                    newDict.Add (b.Key, b.Value);
                }


                return DictionaryToString (newDict);




            }
            /// <summary>
            /// Outputs datatable into tab delimited string.
            /// </summary>
            /// <param name="theDT"></param>
            /// <returns></returns>
            public static string DataTableToString (DataTable theDT)
            {
                return DataTableToString (theDT, Constants.TAB);
            }
            /// <summary>
            /// Outputs datatable into  string (user supplied delimiter).
            /// </summary>
            /// <param name="theDT"></param>
            /// <param name="separator"></param>
            /// <returns></returns>
            public static string DataTableToString (DataTable theDT, string separator)
            {
                StringBuilder sb = new StringBuilder (theDT.Rows.Count * 10);
                foreach (DataColumn dc in theDT.Columns)
                {
                    sb.Append (dc.ColumnName);
                    sb.Append (separator);
                }
                sb.AppendLine ();
                foreach (DataRow dr in theDT.Rows)
                {
                    foreach (object columnObj in dr.ItemArray)
                    {
                        string columnValue = columnObj.ToString ();
                        sb.Append (columnValue);
                        sb.Append (separator);
                    }
                    sb.AppendLine ();
                }
                return sb.ToString ();
            }
            /// <summary>
            /// Returns string with schema info (e.g. column names+data types) present in specified table.
            /// </summary>
            /// <param name="theDT">
            /// A <see cref="DataTable"/>
            /// </param>
            /// <returns>
            /// A <see cref="System.String"/>
            /// </returns>
            public static string DataTableSchemaToString (DataTable theDT)
            {
                return DataTableSchemaToString (theDT, "\t");
            }
            /// <summary>
            /// Returns string with schema info (e.g. column names+data types) present in specified table.
            /// </summary>
            /// <param name="theDT">
            /// A <see cref="DataTable"/>
            /// </param>
            /// <param name="separator">
            /// A <see cref="System.String"/>
            /// </param>
            /// <returns>
            /// A <see cref="System.String"/>
            /// </returns>
            public static string DataTableSchemaToString (DataTable theDT, string separator)
            {
                StringBuilder sb = new StringBuilder (theDT.Columns.Count * 10);
                foreach (DataColumn dc in theDT.Columns)
                {
                    sb.Append (dc.ColumnName);
                    sb.Append (separator);
                    sb.Append (dc.DataType.ToString ().Trim ());
                    sb.Append (separator);
                    sb.Append (dc.Ordinal);
                    sb.Append ("|");
                    
                }
                sb.Append ("<EOR>");
//              foreach (DataRow dr in theDT.Rows) {
//                  foreach (object columnObj in dr.ItemArray) {
//                      string columnValue = columnObj.ToString ();
//                      sb.Append (columnValue);
//                      sb.Append (separator);
//                  }
//                  sb.AppendLine ();
//              }
                return sb.ToString ();
            }

            /// <summary>
            /// Outputs hashtable.
            /// </summary>
            /// <param name="hTable"></param>
            /// <returns></returns>
            public static string HashTableToString (System.Collections.Hashtable hTable)
            {
                StringBuilder sb = new StringBuilder (hTable.Count * 1000);
                foreach (var item in hTable.Keys)
                {
                    sb.Append (item.ToString ());
                    sb.Append ("\t");
                    sb.Append (hTable[item].ToString ());
                    sb.AppendLine ();
                }
                return sb.ToString ();
            }
            /// <summary>
            /// Outputs hashtable. Overload - gives ascending.
            /// </summary>
            /// <param name="hTable"></param>
            /// <param name="ascendingKeyOrder"></param>
            /// <returns></returns>
            public static string HashTableToString (System.Collections.Hashtable hTable, bool ascendingKeyOrder)
            {
                StringBuilder sb = new StringBuilder (hTable.Count * 1000);
                
                Dictionary<int, int> keyDict = new Dictionary<int, int> ();
                Dictionary<int, object> valDict = new Dictionary<int, object> ();
                /*
                 * In the hashtable : 
                 *      Key   is COLUMN 
                 *      Value is FIRST LINE IT OCCURRED
                 * */                
                int i = 0;
                foreach (var item in hTable.Keys)
                {
                    int k = Convert.ToInt16 (item);
                    keyDict.Add (i, k);
                    valDict.Add (i, hTable[item]);
                    i++;
                }
                var items = from k2 in keyDict.Keys
                    orderby keyDict[k2] ascending
                    select k2;
                int x = 0;
                foreach (int k in items)
                {
                    x++;
                    sb.AppendLine (valDict[k].ToString () + "\t" + keyDict[k].ToString ());
                }
                return sb.ToString ();
            }
            /// <summary>
            /// DataRow array to string. Overloaded DataTableToString.
            /// </summary>
            /// <param name="dataRow"></param>
            /// <param name="p"></param>
            /// <returns></returns>
            public static string DataTableToString (DataRow[] dataRow, string p)
            {
                DataTable dt = dataRow.CopyToDataTable<DataRow> ();
                return DataTableToString (dt, p);
            }
        }
    }
}
